#include "socket.hpp"
#include "Log.hxx"
#include <string>
#include <vector>
#include <memory>
#include <array>
#include <sys/select.h>
#include <algorithm>
#include <sys/time.h>
#include "epoller.hpp"

namespace ns_epollServer
{
    using namespace EpollModule;
    using namespace Net_TcpSocket;


    //初始化接受就绪的events个数是64个，会提供接口修改
    const int default_events_num = 64;
    class EpollServer
    {
    public:
        EpollServer(int port);
        ~EpollServer();
        void InitServer();
        void WorkLoop();
        void HanderEvent();
        void DebugPrint();
    private:
        int m_port;
        std::unique_ptr<Socket> m_listen_sock;
        bool m_IsRunning = false;
        Epoller m_epoller;
        std::vector<struct epoll_event> m_events;
    };

    EpollServer::EpollServer(int port)
        : m_port(port), m_listen_sock(new TcpSocket),m_IsRunning(false),m_events(default_events_num)
    {

    }
    void EpollServer::InitServer()
    {
        m_listen_sock->BuildListenSocket(m_port,default_backlog);
        myService::lg(myService::Log::Info,"EpollServer InitServer,Listen Socket is %d\n",m_listen_sock->GetSockfd());
        m_epoller.AddFd(m_listen_sock->GetSockfd(),EPOLLIN);
        myService::lg(myService::Log::Info,"EpollServer InitServer,Listen Socket is %d\n",m_listen_sock->GetSockfd());    }
    EpollServer::~EpollServer()
    {
    }

    void EpollServer::WorkLoop()
    {
        m_IsRunning = true;
        while(m_IsRunning)
        {
            int ret = m_epoller.Wait(m_events.data(),default_events_num);
            switch (ret)
            {

                case -1:
                    myService::lg(myService::Log::Error,"EpollServer WorkLoop,m_epoller.Wait error\n");
                    break;
                case 0:
                    myService::lg(myService::Log::Info,"EpollServer WorkLoop,m_epoller.Wait timeout\n");
                    break; 
                default:
                    m_events.resize(ret);
                    HanderEvent();
            }
        }
    }
    void EpollServer::HanderEvent()
    {
        //显示有几个事件处理
        myService::lg(myService::Log::Debug,"EpollServer HanderEvent,m_events.size() is %d\n",m_events.size());
        for(int i = 0;i < m_events.size();++i)
        {
            if(m_events[i].data.fd == m_listen_sock->GetSockfd())
            {
                if(m_events[i].events & EPOLLIN)
                {
                    std::string ip;uint16_t port;
                    int newsockfd  = m_listen_sock->AcceptRawConnection(&ip,&port);
                    if(newsockfd < 0)
                    {
                        myService::lg(myService::Log::Error,"EpollServer HanderEvent,AcceptRawConnection error\n");
                        continue;
                    }
                    myService::lg(myService::Log::Info,"EpollServer HanderEvent,AcceptRawConnection success,newsockfd is %d\n",newsockfd);
                    //暂时不加入写事件，其和epoll另外工作模式有关
                    m_epoller.AddFd(newsockfd,EPOLLIN);

                }
            }
            else
            {
                //对于普通的套接字，实际还会有写入控制
                if(m_events[i].events & EPOLLIN)
                {
                    std::vector<char> msg(1024);
                    int n = read(m_events[i].data.fd,msg.data(),msg.size()-1);
                    if(n<=0)
                    {
                        if(n<0)
                        {
                            myService::lg(myService::Log::Error,"EpollServer HanderEvent,read error\n");
                        }
                        else
                        {
                            myService::lg(myService::Log::Info,"EpollServer HanderEvent,read close\n");
                        }
                        m_epoller.DelFd(m_events[i].data.fd);
                        close(m_events[i].data.fd);
                        continue;
                    }
                    msg[n] = '\0';
                    myService::lg(myService::Log::Info,"EpollServer HanderEvent,read success,read bytes  is %d\n",n);
                    std::cout<<"Clien Say#$:"<<msg.data()<<std::endl;
                }
                
            }
        }
        
    }
    void EpollServer::DebugPrint()
    {
        //打印已经被epoll管理的文件描述符
        std::cout<<"已经管理的文件描述符\n";
        for(int i = 0;i < m_events.size();++i)
        {   
            std::cout<<m_events[i].data.fd<<" ";
        }
        std::cout<<"\n";
    }

};